#include "serial.h"
#include <string.h>

static uint8_t _uart0_txbuff[UART0_TX_MAX_SIZE];
static uint8_t _uart0_rxbuff[UART0_RX_MAX_SIZE];
static uint8_t _uart1_txbuff[UART1_TX_MAX_SIZE];
static uint8_t _uart1_rxbuff[UART1_RX_MAX_SIZE];

static uart_def _uart_def_objs[UART_ID_MAX]={ UART_DEF(UART_ID_0,M0P_UART0,_uart0_txbuff,UART0_TX_MAX_SIZE,_uart0_rxbuff,UART0_RX_MAX_SIZE),
										      UART_DEF(UART_ID_1,M0P_UART1,_uart1_txbuff,UART1_TX_MAX_SIZE,_uart1_rxbuff,UART1_RX_MAX_SIZE)};

static void _uartx_gpio_init(UART_ID id);
static void _uart_hard_init(UART_ID id);
static void _uart_start_msg(UART_ID id);
													
static void _uart_queue_init(UART_ID id);
static void _uart_rx_queue_insert(UART_ID id, uint8_t data);
static uint32_t _uart_rx_queue_inserts(UART_ID id, uint8_t* data, uint32_t size);
static uint8_t _uart_read_tx_queue(UART_ID id, uint8_t* data);
static uint32_t _uart_reads_tx_queue(UART_ID id, uint8_t* data, uint32_t size);

static void _serial_back_test(void);

#define PORT_IS_ENABLE(id)  (_uart_def_objs[id].enable)
#define PORT_IS_DISABLE(id) (!(_uart_def_objs[id].enable))

#define UART_AUTO_TEST_ENABLE 0

/// 初始化系统配置的各个串口
/// 时钟、GPIO、中断等配置
void uart_init(void)
{
	uint8_t i = 0;
	for( ; i<UART_ID_MAX; ++i)
	{
		if(UARTS_DEF_ENABLE&(1<<i))
		{
			_uart_queue_init((UART_ID)i);	
			_uart_hard_init((UART_ID)i);		
			uart_open((UART_ID)i);
		}
	}
}

/// 往串口fifo中写入数据
static uint8_t _uart_send(UART_ID id)
{
	uint8_t data;
	M0P_UART_TypeDef* huart = _uart_def_objs[id].huart;
	if(UART_DEF_IS_DISABLE(id)) return 0;
	if(_uart_def_objs[id].send_valid)
	{
		if(_uart_read_tx_queue(id, &data))
		{
			_uart_def_objs[id].send_valid = 0;
			huart->SBUF_f.DATA = data;
		}
	}
	return 1;
}

/// 主任务调用
/// 自动读取发送缓存队列中的数据，并通过串口发送
void uart_loop(void)
{
	uint8_t i = 0;
	for( i=0; i<UART_ID_MAX; ++i)
	{
		if(UART_DEF_IS_ENABLE(i) && PORT_IS_ENABLE(i))
		{
			_uart_send((UART_ID)i);
		}
	}

// 串口自动测试代码，串口收数据发数据	
#if UART_AUTO_TEST_ENABLE
	_serial_back_test();
#endif
}

/// 设置波特率
void uart_set_baud(UART_ID id, uint32_t bd)
{
	stc_uart_baud_t uart_baud;
	uart_baud.enRunMode = UartMode1;
	uart_baud.u32Baud = 115200u;
	uart_baud.u32Pclk = 24000000u;
	Uart_SetBaud((uint8_t)id, Uart_CalScnt((uint8_t)id, &uart_baud));
}

/// 上层应用，从接收数据队列中获取串口接收的缓存数据
// read和reads函数不建议在中断处理代码中调用，这样有可能会带来数据不安全访问
int8_t uart_read(UART_ID id, uint8_t* data)
{
	StaticQueue* sq;
	if(UART_DEF_IS_DISABLE(id)) return 0;
	sq = &(_uart_def_objs[id].rx_queue);
	
	if(static_queue_read(sq, data))
		return -1;
	return 0;
}

uint32_t uart_reads(UART_ID id, uint8_t* data, uint32_t size)
{
	StaticQueue* sq;
	if(UART_DEF_IS_DISABLE(id)) return 0;
	
	sq = &(_uart_def_objs[id].rx_queue);
	return static_queue_reads(sq, data, size);
}

uint32_t uart_read_data_len(UART_ID id)
{
	StaticQueue* sq;
	if(UART_DEF_IS_DISABLE(id)) return 0;
	
	sq = &(_uart_def_objs[id].rx_queue);
	return static_queue_len(sq);
}

/// 上层应用，往发送数据队列中写入待发送的数据
// write和writes函数不建议在中断处理代码中调用，这样有可能会带来数据不安全访问
uint8_t uart_write(UART_ID id, uint8_t data)
{
	StaticQueue* sq;
	if(UART_DEF_IS_DISABLE(id) || PORT_IS_DISABLE(id)) return 0;
	
	if(id<UART_ID_MAX)
	{
		sq = &(_uart_def_objs[id].tx_queue);
		static_queue_insert(sq, &data);
	}
	return data;
}

uint32_t uart_writes(UART_ID id, uint8_t* data, uint32_t size)
{
	StaticQueue* sq;
	if(UART_DEF_IS_DISABLE(id) || PORT_IS_DISABLE(id)) return 0;
	
	sq = &(_uart_def_objs[id].tx_queue);
	return static_queue_inserts(sq, data, size);
}

// 串口自收发测试
static void _serial_back_test(void)
{
	uint8_t buff[128];
	const char* bf = "0123456789ABCDEFGHIJKLMOPQRSTUVWXYZ--";
	uint8_t i = 0;
	uint32_t len = 0;
	static uint32_t old_time = 0;
	static uint32_t count = 0;
	uint32_t now = hal_mills();
	if(now-old_time>=5)
	{
		old_time = now;
		for( ; i<UART_ID_MAX; ++i)
		{
			if((UARTS_DEF_ENABLE&(1<<i)) == (1<<i))
			{
				len = uart_reads((UART_ID)i, buff, 128);
				if(len>0)
				{
					count += len;
					uart_writes((UART_ID)i, (uint8_t*)bf, strlen(bf));
					sprintf((char*)buff, "uart-%d rx:%d,%d\r\n", (uint8_t)i, len, count);
					uart_writes((UART_ID)i, buff, strlen((char*)buff));
				}
			}
		}
	}
}

/// 中断相关函数
static void uart_itr_rx(UART_ID id)
{
	if(UART_DEF_IS_DISABLE(id)) return;
	_uart_rx_queue_insert(id, (uint8_t)(_uart_def_objs[id].huart->SBUF_f.DATA));
}

static void uart_itr_tx(UART_ID id)
{
	if(UART_DEF_IS_DISABLE(id)) return;
	_uart_def_objs[id].send_valid = 1;
	_uart_send(id);
}

static void uart0_tx_cmp(void) {uart_itr_tx(UART_ID_0);}
static void uart1_tx_cmp(void) {uart_itr_tx(UART_ID_1);}
static void uart0_rx_cmp(void) {uart_itr_rx(UART_ID_0);}
static void uart1_rx_cmp(void) {uart_itr_rx(UART_ID_1);}

/// 初始化uart对应的GPIO，并设置中断优先级
/// W806芯片各串口引脚分布图
/// uart0: TX-PB8, RX-PB9
/// uart1：TX-PA2,  RX-PA3
static void _uartx_gpio_init(UART_ID id)
{
	stc_gpio_config_t gpio_config; 
	if(UART_DEF_IS_DISABLE(id)) return;
	Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, 1);
	gpio_config.enDrv = GpioDrvH;
	gpio_config.enOD = GpioOdDisable;
	gpio_config.enPuPd = GpioPu;
	gpio_config.enCtrlMode = GpioAHB;
	
	switch(id)
	{
		case UART_ID_0:
		{
			Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0, 1);
			gpio_config.enDir = GpioDirOut;
			Gpio_Init(GpioPortB, GpioPin8, &gpio_config);
			gpio_config.enDir = GpioDirIn;
			Gpio_Init(GpioPortB, GpioPin9, &gpio_config);
			Gpio_SetAfMode(GpioPortB, GpioPin8, GpioAf7);
			Gpio_SetAfMode(GpioPortB, GpioPin9, GpioAf7);
			
			NVIC_SetPriority(UART0_IRQn, 1);
			NVIC_EnableIRQ(UART0_IRQn);
			break;
		}
		case UART_ID_1:
		{
			Sysctrl_SetPeripheralGate(SysctrlPeripheralUart1, 1);
			gpio_config.enDir = GpioDirOut;
			Gpio_Init(GpioPortA, GpioPin2, &gpio_config);
			gpio_config.enDir = GpioDirIn;
			Gpio_Init(GpioPortA, GpioPin3, &gpio_config);
			Gpio_SetAfMode(GpioPortA, GpioPin2, GpioAf1);
			Gpio_SetAfMode(GpioPortA, GpioPin3, GpioAf2);
			
			NVIC_SetPriority(UART1_IRQn, 2);
			NVIC_EnableIRQ(UART1_IRQn);
			break;
		}
		default:
			break;
	}
}

/// 设置uart相关寄存器，使能相关中断
static void _uart_hard_init(UART_ID id)
{	
	stc_uart_config_t uart_config;
	stc_uart_irq_cb_t isr;
	stc_uart_baud_t uart_baud;
	if(UART_DEF_IS_DISABLE(id)) return;
	uart_config.enRunMode = UartMode1;
	uart_config.enStopBit = Uart1bit;
	uart_config.bTouchNvic = 1;
	
	uart_config.pstcIrqCb = &isr;
	uart_config.pstcIrqCb->pfnPEIrqCb = NULL;
	uart_config.pstcIrqCb->pfnCtsIrqCb = NULL;
	uart_config.pstcIrqCb->pfnRxFEIrqCb = NULL;
	
	_uartx_gpio_init(id);
	
	if(id==UART_ID_0)
	{
		uart_config.pstcIrqCb->pfnRxIrqCb = uart0_rx_cmp;
		uart_config.pstcIrqCb->pfnTxIrqCb = uart0_tx_cmp;
	}else{
		uart_config.pstcIrqCb->pfnRxIrqCb = uart1_rx_cmp;
		uart_config.pstcIrqCb->pfnTxIrqCb = uart1_tx_cmp;
	}	
	Uart_Init((uint8_t)id, &uart_config);
	uart_baud.enRunMode = UartMode1;
	uart_baud.u32Baud = 115200u;
	uart_baud.u32Pclk = 24000000u;
	Uart_SetBaud((uint8_t)id, Uart_CalScnt((uint8_t)id, &uart_baud));
	
	Uart_ClrIsr((uint8_t)id);
	Uart_EnableFunc((uint8_t)id, UartTx);
	Uart_EnableFunc((uint8_t)id, UartRx);
}

/// 开启uart收发数据
void uart_open(UART_ID id)
{
	//开启串口收发
	if(UART_DEF_IS_DISABLE(id)) return;
	_uart_def_objs[id].enable = 1;
	Uart_EnableIrq((uint8_t)id, UartRxIrq);
	Uart_EnableIrq((uint8_t)id, UartFEIrq);
	Uart_EnableIrq((uint8_t)id, UartTxIrq);
	_uart_start_msg(id);
}

/// 关闭uart收发数据
void uart_close(UART_ID id)
{
	if(UART_DEF_IS_DISABLE(id)) return;
	Uart_ClrIsr((uint8_t)id);
	Uart_DisableIrq((uint8_t)id, UartRxIrq);
	Uart_DisableIrq((uint8_t)id, UartFEIrq);
	Uart_DisableIrq((uint8_t)id, UartTxIrq);
	_uart_def_objs[id].enable = 0;
}

/// 串口开启消息提醒
static void _uart_start_msg(UART_ID id)
{
	const char* STR = ">> Hello UART%d\r\n";
	char buff[32];
	if(UART_DEF_IS_DISABLE(id)) return;
	sprintf(buff, STR, (uint8_t)id);
	
	uart_writes((UART_ID)id, (uint8_t*)buff, strlen(buff));	
}


/////////// 队列操作相关函数 /////////////////
/// 初始化uart对应的收发队列资源
// 注意：关于队列的插入和读取都没有做互斥处理
static void _uart_queue_init(UART_ID id)
{
	if(UART_DEF_IS_DISABLE(id)) return;
	memset(_uart_def_objs[id].tx_queue.data, 0, _uart_def_objs[id].tx_queue.size);
	memset(_uart_def_objs[id].rx_queue.data, 0, _uart_def_objs[id].rx_queue.size);
}

/// 将接收到的数据保存的接收队列中
static void _uart_rx_queue_insert(UART_ID id, uint8_t data)
{
	StaticQueue* sq;
	if(UART_DEF_IS_DISABLE(id) || PORT_IS_DISABLE(id)) return;
	
	sq = &(_uart_def_objs[id].rx_queue);
	static_queue_insert(sq, &data);
}

static uint32_t _uart_rx_queue_inserts(UART_ID id, uint8_t* data, uint32_t size)
{
	StaticQueue* sq;
	if(UART_DEF_IS_DISABLE(id) || PORT_IS_DISABLE(id)) return 0;
	
	sq = &(_uart_def_objs[id].rx_queue);
	return static_queue_inserts(sq, data, size);
}

/// 读取发送队列中的数据
static uint8_t _uart_read_tx_queue(UART_ID id, uint8_t* data)
{
	StaticQueue* sq;
	if(UART_DEF_IS_DISABLE(id)) return 0;
	sq = &(_uart_def_objs[id].tx_queue);
	
	if(static_queue_read(sq, data))
		return 1;
	return 0;
}

static uint32_t _uart_reads_tx_queue(UART_ID id, uint8_t* data, uint32_t size)
{
	StaticQueue* sq;
	if(UART_DEF_IS_DISABLE(id)) return 0;
	
	sq = &(_uart_def_objs[id].tx_queue);
	return static_queue_reads(sq, data, size);
}

///////////////////////////
/// 
